class_docstr: `LinearOperator` acting like a [batch] of permutation matrices.
  
  This operator acts like a [batch] of permutations with shape
  `[B1,...,Bb, N, N]` for some `b >= 0`.  The first `b` indices index a
  batch member.  For every batch index `(i1,...,ib)`, `A[i1,...,ib, : :]` is
  an `N x N` matrix.  This matrix `A` is not materialized, but for
  purposes of broadcasting this shape will be relevant.
  
  `LinearOperatorPermutation` is initialized with a (batch) vector.
  
  A permutation, is defined by an integer vector `v` whose values are unique
  and are in the range `[0, ... n]`. Applying the permutation on an input
  matrix has the folllowing meaning: the value of `v` at index `i`
  says to move the `v[i]`-th row of the input matrix to the `i`-th row.
  Because all values are unique, this will result in a permutation of the
  rows the input matrix. Note, that the permutation vector `v` has the same
  semantics as `tf.transpose`.
  
  ```python
  # Create a 3 x 3 permutation matrix that swaps the last two columns.
  vec = [0, 2, 1]
  operator = LinearOperatorPermutation(vec)
  
  operator.to_dense()
  ==> [[1., 0., 0.]
       [0., 0., 1.]
       [0., 1., 0.]]
  
  operator.shape
  ==> [3, 3]
  
  # This will be zero.
  operator.log_abs_determinant()
  ==> scalar Tensor
  
  x = ... Shape [3, 4] Tensor
  operator.matmul(x)
  ==> Shape [3, 4] Tensor
  ```
  
  #### Shape compatibility
  
  This operator acts on [batch] matrix with compatible shape.
  `x` is a batch matrix with compatible shape for `matmul` and `solve` if
  
  ```
  operator.shape = [B1,...,Bb] + [N, N],  with b >= 0
  x.shape =   [C1,...,Cc] + [N, R],
  and [C1,...,Cc] broadcasts with [B1,...,Bb] to [D1,...,Dd]
  ```
  
  #### 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 _matmul(self, x, adjoint=False, adjoint_arg=False):
      perm = tensor_conversion.convert_to_tensor_v2_with_dispatch(
          self.perm
      )
      if adjoint and not self.is_self_adjoint:
          # TODO(srvasude): invert_permutation doesn't work on batches so we use
          # argsort.
          perm = sort_ops.argsort(perm, axis=-1)
      x = linalg.adjoint(x) if adjoint_arg else x
  
      # We need to broadcast x and the permutation since tf.gather doesn't
      # broadcast.
      broadcast_shape = array_ops.broadcast_dynamic_shape(
          array_ops.shape(x)[:-1], array_ops.shape(perm)
      )
      k = array_ops.shape(x)[-1]
      broadcast_x_shape = array_ops.concat(
          [broadcast_shape, [k]], axis=-1
      )
      x = array_ops.broadcast_to(x, broadcast_x_shape)
      perm = array_ops.broadcast_to(perm, broadcast_shape)
  
      m = array_ops.shape(x)[-2]
      x = array_ops.reshape(x, [-1, m, k])
      perm = array_ops.reshape(perm, [-1, m])
  
      y = array_ops.gather(x, perm, axis=-2, batch_dims=1)
      return array_ops.reshape(y, broadcast_x_shape)
  
imports: import numpy
  from tensorflow.python.framework import dtypes
  from tensorflow.python.framework import ops
  from tensorflow.python.framework import tensor_conversion
  from tensorflow.python.framework import tensor_util
  from tensorflow.python.ops import array_ops
  from tensorflow.python.ops import control_flow_ops
  from tensorflow.python.ops import math_ops
  from tensorflow.python.ops import sort_ops
  from tensorflow.python.ops.linalg import linalg_impl
  from tensorflow.python.ops.linalg import linear_operator
  from tensorflow.python.ops.linalg import linear_operator_util
  from tensorflow.python.util.tf_export import tf_export
label_desc: Use image node_id 7 for calling the LinearOperatorPermutation obj's underlying member method code with example usage: obj._matmul(x, adjoint, adjoint_arg) and returns: array_ops