<p>To reproduce the numpy example in TensorFlow, please try <code>depth_to_space</code>:</p>

<pre><code>import tensorflow as tf

im = tf.random_normal((1, 8, 8, 2))

phased_im_01 = im[:, ::2, 1::2, :]
phased_im_00 = im[:, ::2, ::2, :]
phased_im_10 = im[:, 1::2, ::2, :]
phased_im_11 = im[:, 1::2, 1::2, :]

phases = tf.concat(
    (phased_im_00, phased_im_01, phased_im_10, phased_im_11), axis=3)
rebuild_im = tf.nn.depth_to_space(phases, block_size=2, data_format='NHWC')

dif = tf.reduce_sum(rebuild_im - im)  # 0.0
</code></pre>

<p>As kindly suggested by <a href="https://stackoverflow.com/users/5024514/shlomif">ShlomiF</a>, the more general example is:</p>

<pre><code>import numpy as np
import tensorflow as tf
tf.enable_eager_execution()

num_of_channels = 20
h = w = 256
num_of_phases = 4
im = np.random.random((1, h, w, num_of_channels))

phase_ims = []
for i in range(num_of_phases):
    for j in range(num_of_phases):
        phase_ims.append(im[:, i::num_of_phases, j::num_of_phases, :])

all_phases = tf.concat(phase_ims, axis=3)
rebuild_im = tf.depth_to_space(all_phases, block_size=num_of_phases, data_format='NHWC')

diff = tf.reduce_sum(rebuild_im - im)
print(np.asarray(diff))  # --&gt; 0.0
</code></pre>

<p>As far as I know, the idea of <code>depth_to_space</code>, or periodic shuffling, came from <a href="https://arxiv.org/abs/1609.05158" rel="nofollow noreferrer">this paper</a>. You may find more details and visualization there. </p>
How does one interleave 4D tensors along the width & height dimensions in tensorflow?
<p>Or: Scattering different phases of multi-channel images in tensorflow...</p>

<p>My question is as follows:<br>
I have "images", all of the same dimensions, which in some sense correspond to different phases of a target image. And I'd like to rebuild that full-blown image with tf functionality.<br>
This turns out to be much less simple than I originally expected and I'd be very grateful for any help!  </p>

<p>A more detailed exposition follows:<br>
In <code>numpy</code>, one easily interleaves images via simple assignment - </p>

<pre><code>import numpy as np

im = np.random.random((1, 8, 8, 2))

phased_im_01 = im[:, ::2, 1::2, :]
phased_im_00 = im[:, ::2, ::2, :]
phased_im_10 = im[:, 1::2, ::2, :]
phased_im_11 = im[:, 1::2, 1::2, :]

rebuild_im = np.zeros((1, 8, 8, 2))
rebuild_im[:, ::2, ::2, :] = phased_im_00
rebuild_im[:, ::2, 1::2, :] = phased_im_01
rebuild_im[:, 1::2, ::2, :] = phased_im_10
rebuild_im[:, 1::2, 1::2, :] = phased_im_11

print(np.all(rebuild_im == im))
</code></pre>

<p>But as known, assignment is a no-go in tf, and one usually uses things like <code>tf.concat</code> coupled with <code>tf.reshape</code> (for very simple cases) or <code>tf.scatter_nd</code> (for more complicated cases). I was unsuccessful in implementing the equivalent of the above numpy-functionality using any of the many things I tried (like permuting the tensor to have the width dimension first, trying to scatter_nd, and permuting back, a method I've successfully used before for other problems), or any solution on SO (like stacking and reshaping oneself to death). </p>

<p>Just to be clear, my actual use-case has an unknown batch-size, thousands of channels, and 4 phases in each image dimension. But I just need a working solution for the simple toy example above; generalization is on me ;-)<br>
Thanks to any helpers out there, (and sorry I can only describe my efforts and not show them. They're just a mess of unsuccessful mistakes degrading into horrible trial-and-error code snippets until giving up and coming here for some help anyway, so no major loss).  </p>

<p>Clarifications can be added on demand.</p>