'Binds the symbols to construct executors. This is necessary before one
can perform computation with the module.
Parameters
data_shapes : list of (str, tuple)
Typically is `data_iter.provide_data`.
label_shapes : list of (str, tuple)
Typically is `data_iter.provide_label`.
for_training : bool
Default is ``True``. Whether the executors should be bind for training.
inputs_need_grad : bool
Default is ``False``. Whether the gradients to the input data need to be computed.
Typically this is not needed. But this might be needed when implementing composition
of modules.
force_rebind : bool
Default is ``False``. This function does nothing if the executors are already
bound. But with this ``True``, the executors will be forced to rebind.
shared_module : Module
Default is ``None``. Currently shared module is not supported for `SequentialModule`.
grad_req : str, list of str, dict of str to str
Requirement for gradient accumulation. Can be \'write\', \'add\', or \'null\'
(default to \'write\').
Can be specified globally (str) or for each argument (list, dict).'

def bind(self, data_shapes, label_shapes=None, for_training=True, inputs_need_grad=False, force_rebind=False, shared_module=None, grad_req='write'):

    if (self.binded and (not force_rebind)):
        self.logger.warning('Already    bound,    ignoring    bind()')
        return
    if inputs_need_grad:
        assert (for_training is True)
    assert (shared_module is None), 'Shared    module    is    not    supported'
    assert (len(self._modules) > 0), 'Attempting    to    bind    an    empty    SequentialModule'
    self.binded = True
    self._label_shapes = label_shapes
    my_data_shapes = data_shapes
    anybody_ever_needs_label = False
    for (i_layer, module) in enumerate(self._modules):
        meta = self._metas[i_layer]
        if ((SequentialModule.META_TAKE_LABELS in meta) and meta[SequentialModule.META_TAKE_LABELS]):
            my_label_shapes = label_shapes
            anybody_ever_needs_label = True
        else:
            my_label_shapes = None
        my_inputs_need_grad = bool((inputs_need_grad or (for_training and (i_layer > 0))))
        if meta.get(SequentialModule.META_AUTO_WIRING, False):
            data_names = module.data_names
            assert (len(data_names) == len(my_data_shapes))
            my_data_shapes = [(new_name, shape) for (new_name, (_, shape)) in zip(data_names, my_data_shapes)]
        module.bind(data_shapes=my_data_shapes, label_shapes=my_label_shapes, for_training=for_training, inputs_need_grad=my_inputs_need_grad, force_rebind=force_rebind, shared_module=None, grad_req=grad_req)
        my_data_shapes = module.output_shapes
    if (not anybody_ever_needs_label):
        self._label_shapes = None
