class_docstr: Composes one or more `LinearOperators`.
  
  This operator composes one or more linear operators `[op1,...,opJ]`,
  building a new `LinearOperator` with action defined by:
  
  ```
  op_composed(x) := op1(op2(...(opJ(x)...))
  ```
  
  If `opj` acts like [batch] matrix `Aj`, then `op_composed` acts like the
  [batch] matrix formed with the multiplication `A1 A2...AJ`.
  
  If `opj` has shape `batch_shape_j + [M_j, N_j]`, then we must have
  `N_j = M_{j+1}`, in which case the composed operator has shape equal to
  `broadcast_batch_shape + [M_1, N_J]`, where `broadcast_batch_shape` is the
  mutual broadcast of `batch_shape_j`, `j = 1,...,J`, assuming the intermediate
  batch shapes broadcast.  Even if the composed shape is well defined, the
  composed operator's methods may fail due to lack of broadcasting ability in
  the defining operators' methods.
  
  ```python
  # Create a 2 x 2 linear operator composed of two 2 x 2 operators.
  operator_1 = LinearOperatorFullMatrix([[1., 2.], [3., 4.]])
  operator_2 = LinearOperatorFullMatrix([[1., 0.], [0., 1.]])
  operator = LinearOperatorComposition([operator_1, operator_2])
  
  operator.to_dense()
  ==> [[1., 2.]
       [3., 4.]]
  
  tensor_shape.TensorShape(operator.shape)
  ==> [2, 2]
  
  operator.log_abs_determinant()
  ==> scalar Tensor
  
  x = ... Shape [2, 4] Tensor
  operator.matmul(x)
  ==> Shape [2, 4] Tensor
  
  # Create a [2, 3] batch of 4 x 5 linear operators.
  matrix_45 = tf.random.normal(shape=[2, 3, 4, 5])
  operator_45 = LinearOperatorFullMatrix(matrix)
  
  # Create a [2, 3] batch of 5 x 6 linear operators.
  matrix_56 = tf.random.normal(shape=[2, 3, 5, 6])
  operator_56 = LinearOperatorFullMatrix(matrix_56)
  
  # Compose to create a [2, 3] batch of 4 x 6 operators.
  operator_46 = LinearOperatorComposition([operator_45, operator_56])
  
  # Create a shape [2, 3, 6, 2] vector.
  x = tf.random.normal(shape=[2, 3, 6, 2])
  operator.matmul(x)
  ==> Shape [2, 3, 4, 2] Tensor
  ```
  
  #### Performance
  
  The performance of `LinearOperatorComposition` on any operation is equal to
  the sum of the individual operators' operations.
  
  
  #### Matrix property hints
  
  This `LinearOperator` is initialized with boolean flags of the form `is_X`,
  for `X = non_singular, self_adjoint, positive_definite, square`.
  These have the following meaning:
  
  * If `is_X == True`, callers should expect the operator to have the
    property `X`.  This is a promise that should be fulfilled, but is *not* a
    runtime assert.  For example, finite floating point precision may result
    in these promises being violated.
  * If `is_X == False`, callers should expect the operator to not have `X`.
  * If `is_X == None` (the default), callers should have no expectation either
    way.
class_docstr_tok: ["Composes","one","or","more","`","LinearOperators","`",".","This","operator","composes","one","or","more","linear","operators","`","[","op1",",","...",",","opJ","]","`",",","building","a","new","`","LinearOperator","`","with","action","defined","by",":","``","`","op_composed","(","x",")",":","=","op1","(","op2","(","...","(","opJ","(","x",")","...",")",")","``","`","If","`","opj","`","acts","like","[","batch","]","matrix","`","Aj","`",",","then","`","op_composed","`","acts","like","the","[","batch","]","matrix","formed","with","the","multiplication","`","A1","A2","...","AJ","`",".","If","`","opj","`","has","shape","`","batch_shape_j","+","[","M_j",",","N_j","]","`",",","then","we","must","have","`","N_j","=","M_","{","j+1","}","`",",","in","which","case","the","composed","operator","has","shape","equal","to","`","broadcast_batch_shape","+","[","M_1",",","N_J","]","`",",","where","`","broadcast_batch_shape","`","is","the","mutual","broadcast","of","`","batch_shape_j","`",",","`","j","=","1",",","...",",","J","`",",","assuming","the","intermediate","batch","shapes","broadcast",".","Even","if","the","composed","shape","is","well","defined",",","the","composed","operator","'s","methods","may","fail","due","to","lack","of","broadcasting","ability","in","the","defining","operators","'","methods",".","``","`","python","#","Create","a","2","x","2","linear","operator","composed","of","two","2","x","2","operators",".","operator_1","=","LinearOperatorFullMatrix","(","[","[","1.",",","2",".","]",",","[","3.",",","4",".","]","]",")","operator_2","=","LinearOperatorFullMatrix","(","[","[","1.",",","0",".","]",",","[","0.",",","1",".","]","]",")","operator","=","LinearOperatorComposition","(","[","operator_1",",","operator_2","]",")","operator.to_dense","(",")","==",">","[","[","1.",",","2",".","]","[","3.",",","4",".","]","]","tensor_shape.TensorShape","(","operator.shape",")","==",">","[","2",",","2","]","operator.log_abs_determinant","(",")","==",">","scalar","Tensor","x","=","...","Shape","[","2",",","4","]","Tensor","operator.matmul","(","x",")","==",">","Shape","[","2",",","4","]","Tensor","#","Create","a","[","2",",","3","]","batch","of","4","x","5","linear","operators",".","matrix_45","=","tf.random.normal","(","shape=","[","2",",","3",",","4",",","5","]",")","operator_45","=","LinearOperatorFullMatrix","(","matrix",")","#","Create","a","[","2",",","3","]","batch","of","5","x","6","linear","operators",".","matrix_56","=","tf.random.normal","(","shape=","[","2",",","3",",","5",",","6","]",")","operator_56","=","LinearOperatorFullMatrix","(","matrix_56",")","#","Compose","to","create","a","[","2",",","3","]","batch","of","4","x","6","operators",".","operator_46","=","LinearOperatorComposition","(","[","operator_45",",","operator_56","]",")","#","Create","a","shape","[","2",",","3",",","6",",","2","]","vector",".","x","=","tf.random.normal","(","shape=","[","2",",","3",",","6",",","2","]",")","operator.matmul","(","x",")","==",">","Shape","[","2",",","3",",","4",",","2","]","Tensor","``","`","#","#","#","#","Performance","The","performance","of","`","LinearOperatorComposition","`","on","any","operation","is","equal","to","the","sum","of","the","individual","operators","'","operations",".","#","#","#","#","Matrix","property","hints","This","`","LinearOperator","`","is","initialized","with","boolean","flags","of","the","form","`","is_X","`",",","for","`","X","=","non_singular",",","self_adjoint",",","positive_definite",",","square","`",".","These","have","the","following","meaning",":","*","If","`","is_X","==","True","`",",","callers","should","expect","the","operator","to","have","the","property","`","X","`",".","This","is","a","promise","that","should","be","fulfilled",",","but","is","*","not","*","a","runtime","assert",".","For","example",",","finite","floating","point","precision","may","result","in","these","promises","being","violated",".","*","If","`","is_X","==","False","`",",","callers","should","expect","the","operator","to","not","have","`","X","`",".","*","If","`","is_X","==","None","`","(","the","default",")",",","callers","should","have","no","expectation","either","way","."]
code: def _shape(self):
      # Get final matrix shape.
      domain_dimension = self.operators[0].domain_dimension
      for operator in self.operators[1:]:
          domain_dimension.assert_is_compatible_with(
              operator.range_dimension
          )
          domain_dimension = operator.domain_dimension
  
      matrix_shape = tensor_shape.TensorShape(
          [
              self.operators[0].range_dimension,
              self.operators[-1].domain_dimension,
          ]
      )
  
      # Get broadcast batch shape.
      # broadcast_shape checks for compatibility.
      batch_shape = self.operators[0].batch_shape
      for operator in self.operators[1:]:
          batch_shape = common_shapes.broadcast_shape(
              batch_shape, operator.batch_shape
          )
  
      return batch_shape.concatenate(matrix_shape)
  
imports: from tensorflow_probability.python.internal.backend.numpy import ops
  from tensorflow_probability.python.internal.backend.numpy import dtype
  from tensorflow_probability.python.internal.backend.numpy import ops
  from tensorflow_probability.python.internal.backend.numpy.gen import tensor_shape
  from tensorflow_probability.python.internal.backend.numpy import numpy_array
  from tensorflow_probability.python.internal.backend.numpy import numpy_array
  from tensorflow_probability.python.internal.backend.numpy import debugging
  from tensorflow_probability.python.internal.backend.numpy import control_flow
  from tensorflow_probability.python.internal.backend.numpy import linalg_impl
  from tensorflow_probability.python.internal.backend.numpy import numpy_math
  from tensorflow_probability.python.internal.backend.numpy.gen import linear_operator
  from tensorflow_probability.python.internal.backend.numpy.gen import linear_operator_lower_triangular
  from tensorflow_probability.python.internal.backend.numpy.gen import linear_operator_util
  import numpy
  from tensorflow_probability.python.internal.backend.numpy import linalg_impl
  from tensorflow_probability.python.internal.backend.numpy import ops
  from tensorflow_probability.python.internal.backend.numpy.gen import tensor_shape
  from tensorflow_probability.python.internal.backend.numpy import private
label_desc: Use image node_id 3 for calling the LinearOperatorComposition obj's underlying member method code with example usage: obj._shape() and returns: batch_shape