docs: def sample(self, model, num_samples, epsilon,
                 lmin=1, lmax=1, thin=1, burn=0,
                 session=None, initialize=True, anchor=True,
                 logprobs=True):
          """
          A straight-forward HMC implementation. The mass matrix is assumed to be the
          identity.
  
          The gpflow model must implement `build_objective` method to build `f` function
          (tensor) which in turn based on model's internal trainable parameters `x`.
  
              f(x) = E(x)
  
          we then generate samples from the distribution
  
              pi(x) = exp(-E(x))/Z
  
          The total number of iterations is given by:
  
              burn + thin * num_samples
  
          The leafrog (Verlet) integrator works by picking a random number of steps
          uniformly between lmin and lmax, and taking steps of length epsilon.
  
          :param model: gpflow model with `build_objective` method implementation.
          :param num_samples: number of samples to generate.
          :param epsilon: HMC tuning parameter - stepsize.
          :param lmin: HMC tuning parameter - lowest integer `a` of uniform `[a, b]` distribution
              used for drawing number of leapfrog iterations.
          :param lmax: HMC tuning parameter - largest integer `b` from uniform `[a, b]` distribution
              used for drawing number of leapfrog iterations.
          :param thin: an integer which specifies the thinning interval.
          :param burn: an integer which specifies how many initial samples to discard.
          :param session: TensorFlow session. The default session or cached GPflow session
              will be used if it is none.
          :param initialize: indication either TensorFlow initialization is required or not.
          :param anchor: dump live trainable values computed within specified TensorFlow
              session to actual parameters (in python scope).
          :param logprobs: indicates either logprob values shall be included in output or not.
  
          :return: data frame with `num_samples` traces, where columns are full names of
              trainable parameters except last column, which is `logprobs`.
              Trainable parameters are represented as constrained values in output.
  
          :raises: ValueError exception in case when wrong parameter ranges were passed.
          """
  
          if lmax <= 0 or lmin <= 0:
              raise ValueError('The lmin and lmax parameters must be greater zero.')
          if thin <= 0:
              raise ValueError('The thin parameter must be greater zero.')
          if burn < 0:
              raise ValueError('The burn parameter must be equal or greater zero.')
  
          lmax += 1
          session = model.enquire_session(session)
  
          model.initialize(session=session, force=initialize)
  
          with tf.name_scope('hmc'):
              params = list(model.trainable_parameters)
              xs = list(model.trainable_tensors)
  
              def logprob_grads():
                  logprob = tf.negative(model.build_objective())
                  grads = tf.gradients(logprob, xs)
                  return logprob, grads
  
              thin_args = [logprob_grads, xs, thin, epsilon, lmin, lmax]
  
              if burn > 0:
                  burn_op = _burning(burn, *thin_args)
                  session.run(burn_op, feed_dict=model.feeds)
  
              xs_dtypes = _map(lambda x: x.dtype, xs)
              logprob_dtype = model.objective.dtype
              dtypes = _flat(xs_dtypes, [logprob_dtype])
              indices = np.arange(num_samples)
  
              def map_body(_):
                  xs_sample, logprob_sample = _thinning(*thin_args)
                  return _flat(xs_sample, [logprob_sample])
  
              hmc_output = tf.map_fn(map_body, indices, dtype=dtypes,
                                     back_prop=False, parallel_iterations=1)
              with tf.control_dependencies(hmc_output):
                  unconstrained_trace, logprob_trace = hmc_output[:-1], hmc_output[-1]
                  constrained_trace = _map(lambda x, param: param.transform.forward_tensor(x),
                                           unconstrained_trace, params)
                  hmc_output = constrained_trace + [logprob_trace]
  
          names = [param.pathname for param in params]
          raw_traces = session.run(hmc_output, feed_dict=model.feeds)
  
          if anchor:
              model.anchor(session)
  
          traces = dict(zip(names, map(list, raw_traces[:-1])))
          if logprobs:
              traces.update({'logprobs': raw_traces[-1]})
          return pd.DataFrame(traces)