code: def sg_periodic_shuffle(tensor, opt):
      r
      # default factor
      opt += tf.sg_opt(factor=2)
  
      # get current shape
      batch, row, col, channel = tensor.get_shape().as_list()
  
      # get target channel num
      channel_target = channel // (opt.factor * opt.factor)
      channel_factor = channel // channel_target
  
      # intermediate shape for shuffling
      shape_1 = [batch, row, col, channel_factor // opt.factor, channel_factor // opt.factor]
      shape_2 = [batch, row * opt.factor, col * opt.factor, 1]
  
      # reshape and transpose for periodic shuffling for each channel
      out = []
      for i in range(channel_target):
          out.append((tensor[:, :, :, i*channel_factor:(i+1)*channel_factor])
                     .sg_reshape(shape=shape_1)
                     .sg_transpose(perm=(0, 1, 3, 2, 4))
                     .sg_reshape(shape=shape_2))
  
      # final output
      out = tf.concat(out, 3)
  
      return tf.identity(out, name=opt.name)
docs: r""" Periodic shuffle transformation for SubPixel CNN.
          (see [Shi et al. 2016](http://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Shi_Real-Time_Single_Image_CVPR_2016_paper.pdf)
          
      Args:
        tensor: A tensor (automatically given by chain).
        opt:
          factor: factor to multiply shape by. Default is 2.
          name : If provided, it replaces current tensor's name.
  
      Returns:
          A tensor