'Allocate input and output buffer for layer based on batch size. This
is used because the layer does not know about the batch size.
Arguments:
dim0 (tuple or int): I/O buffer dimension for layer (without the
axis specifying the batch size).
x (data-type, optional): If present and not None, `x` will be
returned directly. `x` will be not None if
the buffer has already been allocated.
dtype (data-type, optional): If present, specifies the underlying
type to employ for each element.
name (str, optional): name indentifying the tensor (used in printing).
persist_values (bool, optional): If set to True (the default), the
values assigned to this Tensor will
persist across multiple begin and
end calls.  Setting to False may
provide a performance increase if
values do not need to be maintained
across such calls
shared (buffer, optional): If present will attempt to reuse the memory
in shared to allocate the I/O buffer
parallelism (str, optional): Indicates type of parallelism (Data,
Model) employed by this buffer.
Ignored on CPU and GPU backends,
defaults to no parallelism.
Returns:
Tensor: array object'

def iobuf(self, dim0, x=None, dtype=None, name=None, persist_values=True, shared=None, parallelism=None):

    if (x is not None):
        return x
    if isinstance(dim0, tuple):
        if (len(dim0) == 2):
            bufshape = (dim0[0], (dim0[1] * self.bsz))
        else:
            bufshape = (int(np.prod(dim0)), self.bsz)
    else:
        bufshape = (dim0, self.bsz)
    if (shared is not None):
        out_tsr = (shared if (shared.shape == bufshape) else shared.share(bufshape))
    else:
        out_tsr = self.empty(bufshape, dtype=dtype, name=name, persist_values=persist_values)
    out_tsr[:] = 0
    return out_tsr
