code: def rotate_transpose(x, shift, name="rotate_transpose"):
      """Circularly moves dims left or right.
  
      Effectively identical to:
  
      ```python
      numpy.transpose(x, numpy.roll(numpy.arange(len(x.shape)), shift))
      ```
  
      When `validate_args=False` additional graph-runtime checks are
      performed. These checks entail moving data from to GPU to CPU.
  
      Example:
  
      ```python
      x = tf.random.normal([1, 2, 3, 4])  # Tensor of shape [1, 2, 3, 4].
      rotate_transpose(x, -1).shape == [2, 3, 4, 1]
      rotate_transpose(x, -2).shape == [3, 4, 1, 2]
      rotate_transpose(x,  1).shape == [4, 1, 2, 3]
      rotate_transpose(x,  2).shape == [3, 4, 1, 2]
      rotate_transpose(x,  7).shape == rotate_transpose(x, 3).shape  # [2, 3, 4, 1]
      rotate_transpose(x, -7).shape == rotate_transpose(x, -3).shape  # [4, 1, 2, 3]
      ```
  
      Args:
        x: `Tensor`.
        shift: `Tensor`. Number of dimensions to transpose left (shift<0) or
          transpose right (shift>0).
        name: Python `str`. The name to give this op.
  
      Returns:
        rotated_x: Input `Tensor` with dimensions circularly rotated by shift.
  
      Raises:
        TypeError: if shift is not integer type.
      """
      with tf.name_scope(name):
          x = tf.convert_to_tensor(x, name="x")
          shift = ps.convert_to_shape_tensor(shift, name="shift")
          # We do not assign back to preserve constant-ness.
          assert_util.assert_integer(shift)
          shift_value_static = tf.get_static_value(shift)
          ndims = tensorshape_util.rank(x.shape)
          if ndims is not None and shift_value_static is not None:
              if ndims < 2:
                  return x
              shift_value_static = np.sign(shift_value_static) * (
                  abs(shift_value_static) % ndims
              )
              if shift_value_static == 0:
                  return x
              perm = np.roll(np.arange(ndims), shift_value_static)
              return tf.transpose(a=x, perm=perm)
          else:
              # Consider if we always had a positive shift, and some specified
              # direction.
              # When shifting left we want the new array:
              #   last(x, n-shift) + first(x, shift)
              # and if shifting right then we want:
              #   last(x, shift) + first(x, n-shift)
              # Observe that last(a) == slice(a, n) and first(a) == slice(0, a).
              # Also, we can encode direction and shift as one: direction * shift.
              # Combining these facts, we have:
              #   a = cond(shift<0, -shift, n-shift)
              #   last(x, n-a) + first(x, a) == x[a:n] + x[0:a]
              # Finally, we transform shift by modulo length so it can be specified
              # independently from the array upon which it operates (like python).
              ndims = tf.rank(x)
              shift = tf.where(
                  tf.less(shift, 0),
                  -shift % ndims,
                  ndims - shift % ndims,
              )
              first = tf.range(0, shift)
              last = tf.range(shift, ndims)
              perm = tf.concat([last, first], 0)
              return tf.transpose(a=x, perm=perm)
  
imports: import functools
  import hashlib
  import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.internal import assert_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import reparameterization
  from tensorflow_probability.python.internal import tensorshape_util
  from tensorflow.python.util import tf_inspect
label_desc: Use image node_id 30 for calling a global function with example usage: rotate_transpose(x, shift, name) and returns: tf, tf, x, x