'Apply the forward pass transformation to the input data.
Arguments:
inputs (list): list of Tensors with one such tensor for each time
step of model unrolling.
inference (bool, optional): Set to true if you are running
inference (only care about forward
propagation without associated backward
propagation).  Default is False.
Returns:
Tensor: LSTM output for each model time step'

def fprop(self, inputs, inference=False):

    self.init_buffers(inputs)
    if self.reset_cells:
        self.h_f[(-1)][:] = 0
        self.c_f[(-1)][:] = 0
        self.h_b[0][:] = 0
        self.c_b[0][:] = 0
    params_f = (self.h_f, self.h_prev, self.xs_f, self.ifog_f, self.ifo_f, self.i_f, self.f_f, self.o_f, self.g_f, self.c_f, self.c_prev, self.c_act_f)
    params_b = (self.h_b, self.h_next, self.xs_b, self.ifog_b, self.ifo_b, self.i_b, self.f_b, self.o_b, self.g_b, self.c_b, self.c_next, self.c_act_b)
    self.be.compound_dot(self.W_input_f, self.x_f, self.ifog_buffer_f)
    self.be.compound_dot(self.W_input_b, self.x_b, self.ifog_buffer_b)
    for (h, h_prev, xs, ifog, ifo, i, f, o, g, c, c_prev, c_act) in zip(*params_f):
        self.be.compound_dot(self.W_input_f, xs, ifog)
        self.be.compound_dot(self.W_recur_f, h_prev, ifog, beta=1.0)
        ifog[:] = (ifog + self.b_f)
        ifo[:] = self.gate_activation(ifo)
        g[:] = self.activation(g)
        c[:] = ((f * c_prev) + (i * g))
        c_act[:] = self.activation(c)
        h[:] = (o * c_act)
    for (h, h_next, xs, ifog, ifo, i, f, o, g, c, c_next, c_act) in reversed(list(zip(*params_b))):
        self.be.compound_dot(self.W_recur_b, h_next, ifog)
        self.be.compound_dot(self.W_input_b, xs, ifog, beta=1.0)
        ifog[:] = (ifog + self.b_b)
        ifo[:] = self.gate_activation(ifo)
        g[:] = self.activation(g)
        c[:] = ((f * c_next) + (i * g))
        c_act[:] = self.activation(c)
        h[:] = (o * c_act)
    return self.h_buffer
