class_docstr: Permutes tensor ``x`` dimensions according to ``perm``.
  
  Parameters
  ----------
  x: tensor<*?, T> (Required)
      * Must be at least 1D. ``x`` may have symbolic shape.
  perm: const<[rank(x)], i32> (Required)
      * Permutation order. Must be non-negative integers.
  
  Returns
  -------
  tensor<*?,T>
      * Tensor with same rank and type as ``x``.
  
  Attributes
  ----------
  T: fp32
code: def type_inference(self):
      x_type = self.x.dtype
      perm = self.perm.val
      x_shape = np.array(self.x.shape)
      if len(perm) != self.x.rank:
          msg = "perm should have the same length as rank(x): {} != {}"
          raise ValueError(msg.format(len(perm), self.x.rank))
      if self.x.rank == 0:
          return self.x.sym_type  # scalar cannot be transposed
      if any_variadic(self.x.shape):
          ret_shape = get_new_variadic_symbol()
      else:
          ret_shape = x_shape[perm]
      return types.tensor(x_type, tuple(ret_shape))
  
imports: import functools
  import sympy
  from coremltools.converters.mil.mil.types.symbolic import is_symbolic, isscalar, any_symbolic, any_variadic
  from coremltools.converters.mil.mil import get_new_symbol, get_new_variadic_symbol, VALUE, SYMBOL, types
  from ._op_reqs import *
label_desc: Use image node_id 2 for calling the transpose obj's underlying member method code with example usage: obj.type_inference() and returns: types, self