code: def tile(cls, op):
      from ..merge import concatenate
  
      axes = op.axes
      in_tensor = op.input
      is_inverse = cls._is_inverse()
  
      if has_unknown_shape(in_tensor):
          yield
  
      x = in_tensor
      for axis in axes:
          size = in_tensor.shape[axis]
          slice_on = (size + 1) // 2 if not is_inverse else size // 2
          slc1 = [slice(None)] * axis + [slice(slice_on)]
          slc2 = [slice(None)] * axis + [slice(slice_on, None)]
          x = concatenate([x[slc2], x[slc1]], axis=axis)
  
      x = yield from recursive_tile(x)
      new_op = op.copy()
      return new_op.new_tensors(
          op.inputs,
          op.outputs[0].shape,
          chunks=x.chunks,
          nsplits=x.nsplits,
      )
  
imports: from collections.abc import Iterable
  from ...core import recursive_tile
  from ...serialization.serializables import FieldTypes, KeyField, StringField, Int32Field, Int64Field, TupleField
  from ...utils import has_unknown_shape
  from ..utils import validate_axis, decide_chunk_sizes
  from ..operands import TensorHasInput, TensorOperandMixin
  from ..array_utils import get_array_module
label_desc: Use image node_id 3 for calling the TensorFFTShiftMixin obj's underlying member method code with example usage: obj.tile(cls, op) and returns: new_op