'Returns a list of (success, response) tuples.  If success
is False, response will be an Exception.  Otherwise, response
will be the normal query response.
If fail_on_error was left as True and one of the requests
failed, the corresponding Exception will be raised.'

def wait_for_responses(self, *msgs, **kwargs):

    if (self.is_closed or self.is_defunct):
        raise ConnectionShutdown(('Connection    %s    is    already    closed' % (self,)))
    timeout = kwargs.get('timeout')
    fail_on_error = kwargs.get('fail_on_error', True)
    waiter = ResponseWaiter(self, len(msgs), fail_on_error)
    messages_sent = 0
    while True:
        needed = (len(msgs) - messages_sent)
        with self.lock:
            available = min(needed, ((self.max_request_id - self.in_flight) + 1))
            request_ids = [self.get_request_id() for _ in range(available)]
            self.in_flight += available
        for (i, request_id) in enumerate(request_ids):
            self.send_msg(msgs[(messages_sent + i)], request_id, partial(waiter.got_response, index=(messages_sent + i)))
        messages_sent += available
        if (messages_sent == len(msgs)):
            break
        else:
            if (timeout is not None):
                timeout -= 0.01
                if (timeout <= 0.0):
                    raise OperationTimedOut()
            time.sleep(0.01)
    try:
        return waiter.deliver(timeout)
    except OperationTimedOut:
        raise
    except Exception as exc:
        self.defunct(exc)
        raise
