Context manager which changes the representation of parameters and data holders
    for the specific parameterized object(s).

    This can also be used to turn off tensor conversion functions wrapped with
    `params_as_tensors`:
    ```
    @gpflow.params_as_tensors
    def compute_something(self):  # self is parameterized object.
        s = tf.reduce_sum(self.a) # self.a is a parameter.
        with params_as_tensors_for(self, convert=False):
            b = self.c.constrained_tensor
        return s + b
    ```

    :param objs: one or more instances of classes deriving from Parameterized
    :param convert: Flag which is used for turning tensor convertion
        feature on, `True`, or turning it off, `False`.

def params_as_tensors_for(*objs, convert=True):
    """
    Context manager which changes the representation of parameters and data holders
    for the specific parameterized object(s).

    This can also be used to turn off tensor conversion functions wrapped with
    `params_as_tensors`:
    ```
    @gpflow.params_as_tensors
    def compute_something(self):  # self is parameterized object.
        s = tf.reduce_sum(self.a) # self.a is a parameter.
        with params_as_tensors_for(self, convert=False):
            b = self.c.constrained_tensor
        return s + b
    ```

    :param objs: one or more instances of classes deriving from Parameterized
    :param convert: Flag which is used for turning tensor convertion
        feature on, `True`, or turning it off, `False`.
    """
    objs = set(objs)  # remove duplicate objects so the tensor mode won't be changed before saving
    prev_values = [_params_as_tensors_enter(o, convert) for o in objs]
    try:
        yield
    finally:
        for o, pv in reversed(list(zip(objs, prev_values))):
            _params_as_tensors_exit(o, pv)