After posting my other answer to this question, I realized that it did not address how to center a multi-line TextView.

Referring to the image above, the leftmost box has a single line TextView. The TextView and the ImageView are centered as a group in the the box. This was accomplished by specifying the following for the TextView.
<TextView
    android:layout_width="0dp"
    app:layout_constraintWidth_default="wrap" 
    .. the rest of it .../>
See this posting regarding the use of app:layout_constraintWidth_default="wrap".
app:layout_constraintWidth_default="wrap" (with width set to 0dp). If set, the widget will have the same size as if using wrap_content, but will be limited by constraints (i.e. it won't expand beyond them)
Update: It looks like the XML above needs to be changed for ConstraintLayout 1.1.0 beta2. See the release update.
I think what we are now looking for in the XML is the following:
<TextView
    android:layout_width="wrap_content"
   app:layout_constrainedWidth="true"
    .. the rest of it .../>
I have left the rest of this posting using the pre-1.1.0 beta2 layout. To update, just make the changes mentioned above. The centering issue remains.
This works great for the single line example and the views are centered in the box, but we run into difficulty when the TextView spans multiple lines as it does in the middle box of image above. Although the text within the TextView is wrapped and does not expand beyond its constraints, the ImageView and TextView are not centered like we might expect. In fact, the bounds of the TextView extend to the right of the blue box.
My quick fix for this is to insert a zero-width Space widget  to the left of the ImageView in the rightmost box. The chain is that box is now anchored between the Space widget and the righthand side of the box. The ImageView is constrained on the left by the Space.
The Space widget can now be expanded to act like a shim to move the ImageView to the right by the amount that will center the chain. (See right box in the image above.) The getExcessWidth() method of MainActivity calculates how wide the Space widget needs to be.
Here is the XML:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <View
        android:id="@+id/element_1"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="32dp"
        android:background="@color/colorPrimary"
        app:layout_constraintEnd_toStartOf="@+id/element_2"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <View
        android:id="@+id/element_2"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="32dp"
        android:background="@color/colorPrimary"
        app:layout_constraintEnd_toStartOf="@+id/element_3"
        app:layout_constraintStart_toEndOf="@+id/element_1"
        app:layout_constraintTop_toTopOf="parent" />
    <View
        android:id="@+id/element_3"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="32dp"
        android:background="@color/colorPrimary"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/element_2"
        app:layout_constraintTop_toTopOf="parent" />
    <ImageView
        android:id="@+id/image1"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_marginLeft="8dp"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintBottom_toBottomOf="@id/element_1"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toLeftOf="@id/element_1"
        app:layout_constraintRight_toLeftOf="@+id/text1"
        app:layout_constraintTop_toTopOf="@id/element_1" />
    <ImageView
        android:id="@+id/image2"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_marginLeft="8dp"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintBottom_toBottomOf="@id/element_2"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toLeftOf="@id/element_2"
        app:layout_constraintRight_toLeftOf="@+id/text2"
        app:layout_constraintTop_toTopOf="@id/element_2" />
    <android.support.v4.widget.Space
        android:id="@+id/spacer3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="@id/element_3"
        app:layout_constraintLeft_toLeftOf="@id/element_3"
        app:layout_constraintTop_toTopOf="@id/element_3" />
    <ImageView
        android:id="@+id/image3"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_marginLeft="8dp"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintBottom_toBottomOf="@id/element_3"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toRightOf="@id/spacer3"
        app:layout_constraintRight_toLeftOf="@id/text3"
        app:layout_constraintTop_toTopOf="@id/element_3" />
    <TextView
        android:id="@+id/text1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="8dp"
        android:gravity="center_vertical"
        android:text="String"
        android:textColor="@android:color/white"
        app:layout_constraintBottom_toBottomOf="@id/element_1"
        app:layout_constraintLeft_toRightOf="@id/image1"
        app:layout_constraintRight_toRightOf="@id/element_1"
        app:layout_constraintTop_toTopOf="@id/element_1"
        app:layout_constraintWidth_default="wrap" />
    <TextView
        android:id="@+id/text2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="8dp"
        android:gravity="center_vertical"
        android:text="A 2-line string"
        android:textColor="@android:color/white"
        app:layout_constraintBottom_toBottomOf="@id/element_2"
        app:layout_constraintLeft_toRightOf="@id/image2"
        app:layout_constraintRight_toRightOf="@id/element_2"
        app:layout_constraintTop_toTopOf="@id/element_2"
        app:layout_constraintWidth_default="wrap" />
    <TextView
        android:id="@+id/text3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginRight="8dp"
        android:gravity="center_vertical"
        android:text="A 2-line string"
        android:textColor="@android:color/white"
        app:layout_constraintBottom_toBottomOf="@id/element_3"
        app:layout_constraintLeft_toRightOf="@id/image3"
        app:layout_constraintRight_toRightOf="@id/element_3"
        app:layout_constraintTop_toTopOf="@id/element_3"
        app:layout_constraintWidth_default="wrap" />
</android.support.constraint.ConstraintLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.chained_chains);
        ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.constraintLayout);
        layout.post(new Runnable() {
            @Override
            public void run() {
                final TextView textView = (TextView) findViewById(R.id.text3);
                int excessWidth = getExcessWidth(textView);
                if (excessWidth > 0) {
                    Space spacer = (Space) findViewById(R.id.spacer3);
                    ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams) spacer.getLayoutParams();
                    lp.width = getExcessWidth(textView) / 2;
                    spacer.setLayoutParams(lp);
                }
            }
        });
    }
    private int getExcessWidth(TextView textView) {
        if (textView.getLineCount() <= 1) {
            return 0;
        }
        Layout layout = textView.getLayout();
        int maxWidth = 0;
        for (int i = 0; i < textView.getLineCount(); i++) {
            maxWidth = Math.max(maxWidth, (int) layout.getLineWidth(i));
        }
        return Math.max(textView.getWidth() - maxWidth, 0);
    }
}