code: @SuppressWarnings("WeakerAccess")
    public final <R> Optional<R> apply(Timeout timeout, Function<T, R> function)
        throws InterruptedException {
      T obj = claim(timeout);
      if (obj == null) {
        return Optional.empty();
      }
      try {
        return Optional.ofNullable(function.apply(obj));
      } finally {
        obj.release();
      }
    }
docs: Claim an object from the pool and apply the given function to it, returning
  the result and releasing the object back to the pool.
  
  If an object cannot be claimed within the given timeout, then
  {@link Optional#empty()} is returned instead. The `empty()` value is also
  returned if the function returns `null`.
  
  @param timeout The timeout of the maximum permitted amount of time to wait
  for an object to become available. A timeout with a value of zero or less
  means that the call will do no waiting, preferring instead to return early
  if no objects are available.
  @param function The function to apply to the claimed object, if any. The
  function should avoid further claims, since having more than one object
  claimed at a time per thread is inherently deadlock prone.
  @param <R> The return type of the given function.
  @return an {@link Optional} of either the return value of applying the
  given function to a claimed object, or empty if the timeout elapsed or
  the function returned `null`.
  @throws InterruptedException if the thread was interrupted.
  @see #claim(Timeout) The `claim` method for more details on failure modes
  and memory effects.