def subjects(auth, label=None, project=None):
    '''
    Retrieve Subject tuples for subjects returned by this function.
    
    Example:
        >>> import yaxil
        >>> auth = yaxil.XnatAuth(url='...', username='...', password='...')
        >>> yaxil.subjects(auth, 'AB1234C')
        Subject(uri=u'/data/experiments/XNAT_S0001', label=u'AB1234C', id=u'XNAT_S0001', 
            project=u'MyProject')

    :param auth: XNAT authentication
    :type auth: :mod:`yaxil.XnatAuth`
    :param label: XNAT Subject label
    :type label: str
    :param project: XNAT Subject Project
    :type project: str
    :returns: Subject objects
    :rtype: :mod:`yaxil.Subject`
    '''
    url = '{0}/data/subjects'.format(auth.url.rstrip('/'))
    logger.debug('issuing http request %s', url)
    # compile query string
    columns = [
        'ID',
        'label',
        'project'
    ]
    payload = {
        'columns': ','.join(columns)
    }
    if label:
        payload['label'] = label
    if project:
        payload['project'] = project
    # submit the request
    r = requests.get(url, params=payload, auth=(auth.username, auth.password), 
                     verify=CHECK_CERTIFICATE)
    # validate response
    if r.status_code != requests.codes.ok:
        raise AccessionError('response not ok ({0}) from {1}'.format(r.status_code, r.url))
    try:
        results = r.json()
        __quick_validate(results)
    except ResultSetError as e:
        raise ResultSetError('{0} from {1}'.format(e.message, r.url))
    results = results['ResultSet']
    if int(results['totalRecords']) == 0:
        raise NoSubjectsError('no records returned from {0}'.format(r.url))
    # start generating consumable results for the caller
    for item in results['Result']:
        yield Subject(uri=item['URI'],
                      id=item['ID'],
                      project=item['project'],
                      label=item['label'])