Convert an array with shape of (B, C, H, W) into a tiled image.

    Args:
        data (~numpy.ndarray): An array with shape of (B, C, H, W).
        padsize (int): Each tile has padding with this size.
        padval (float): Padding pixels are filled with this value.

    Returns:
        tile_image (~numpy.ndarray): A tile image.

def tile_images(data, padsize=1, padval=0):
    """
    Convert an array with shape of (B, C, H, W) into a tiled image.

    Args:
        data (~numpy.ndarray): An array with shape of (B, C, H, W).
        padsize (int): Each tile has padding with this size.
        padval (float): Padding pixels are filled with this value.

    Returns:
        tile_image (~numpy.ndarray): A tile image.

    """
    assert(data.ndim == 4)
    data = data.transpose(0, 2, 3, 1)

    # force the number of filters to be square
    n = int(np.ceil(np.sqrt(data.shape[0])))
    padding = (
        (0, n ** 2 - data.shape[0]),
        (0, padsize),
        (0, padsize)
    ) + ((0, 0),) * (data.ndim - 3)
    data = np.pad(
        data, padding, mode='constant', constant_values=(padval, padval))
    data = data.reshape(
        (n, n)
        + data.shape[1:]
    ).transpose((0, 2, 1, 3) + tuple(range(4, data.ndim + 1)))
    data = data.reshape(
        (n * data.shape[1], n * data.shape[3]) + data.shape[4:])
    if data.shape[2] == 1:
        # Return as (H, W)
        return data.reshape(data.shape[:2])
    return data