¿Cómo cambiar el avatar del usuario?
Los avatares están diseñados para ser controlados por el usuario, no por ti. Así que sí, en cierto modo, estás obligado a utilizar el servicio de Gravatar. Pero recuerda que le da al usuario la capacidad de usar el mismo avatar en cualquier lugar, y siempre puedes restringir la visualización de un gravatar basado en clasificaciones de contenido (G, PG, PG-13, R).
Gravatar es un servicio alojado, por eso no hay una sección de "Subir Avatar" en el perfil.
Dices que "no puedes usar un plugin", pero en realidad esa es la única manera de añadir funcionalidades. Si quieres usar algo diferente a Gravatar, necesitarás cargar un plugin para soportarlo. Hay algunos plugins que soportan avatares locales:
De lo contrario, te recomiendo que eduques a tus usuarios sobre qué son los Gravatars y cómo usarlos.

¡Eso es TOTALMENTE INCORRECTO! No tengo que educar a mis usuarios, porque quiero cambiar el avatar del administrador, etc. Y no puedo hacerlo. Y por lo que recuerdo, ¿había una opción como esta? ;/ Esto me obliga a usar algún sitio extraño que ni siquiera quiero usar. Es MUY EXTRAÑO. Imagina que quiero configurar un blog para una red empresarial local sin acceso a internet (por razones de seguridad, datos restringidos), etc. Y ni siquiera es posible sin un plugin. Qué vergüenza.

@Wordpressor: Cuando dices "eso es totalmente incorrecto", ¿te refieres a que la respuesta de EAMann es incorrecta o es la situación con la que no estás de acuerdo? Gravatar es propiedad de Automattic, la empresa de Matt Mullenweg, quien decide qué se incluye en WordPress. Probablemente esa sea la razón por la que solo lo admiten de forma nativa, y delegan otros métodos a los plugins.

@Wordpressor: si lo ejecutas dentro de una empresa, probablemente también querrás un LDAP para propósitos de seguridad y un inicio de sesión único. Esa es tu clave: también querrías una ubicación única para la "imagen de usuario". Fuera de la aplicación.

@Jan Fabry: su respuesta está bien, pero toda la política NO lo está. Estoy desarrollando mi propio tema en mi propio PC. Solo tengo un usuario allí: admin. Quiero cambiar su avatar. Puedo capturarlo, mostrarlo, cambiar su tamaño, pero no puedo cambiarlo. Esto no es agradable. Y tener que dar mi correo solo para poder cambiar mi propio avatar es simplemente ridículo.

@Jan Fabry: ¡JAJA! Es aún más gracioso. Tengo que crear una entrada adicional en mi panel de administración, porque mi usuario tiene que enviar su ID de Gravatar al back-end. ¡GUAUUUU! ¡INCREÍBLE! Te odio Matt Mullenweg.

@Wordpressor Para el contexto Decisiones no Opciones es uno de los pilares fundamentales de cómo se hacen las cosas en WordPress. Usar gravatars por defecto es una decisión que tiene suficiente sentido, es lo suficientemente flexible y promueve un servicio afiliado. Y cuando se toma una decisión, generalmente son los plugins los que proporcionan ajustes o alternativas.

Si te preguntas cómo reemplazar el gravatar predeterminado con uno propio, puedes colocar este código en el archivo functions.php (o mejor aún, en custom-functions.php si tu tema lo soporta).
add_filter( 'avatar_defaults', 'customgravatar' );
function customgravatar ($avatar_defaults) {
$myavatar = get_home_url('Template_directory') . '/images/mycustomgravatar.jpg';
$avatar_defaults[$myavatar] = "Mi Logo Personalizado";
return $avatar_defaults;
}
Crea un archivo de imagen y súbelo al directorio de imágenes de tu sitio. El texto "Mi Logo Personalizado" es la etiqueta para la opción en la sección de Discusión de tu Panel de Control. De esta manera, cualquier usuario que no tenga un gravatar obtendrá el logo de tu sitio en su lugar.

Necesitas un poco más de código para que el hook avatar_defaults funcione correctamente que en la respuesta de Ray Mitchell. Encontré este código en las páginas del codex de WordPress y funcionó bien gracias al ID de usuario normalizado que se pasa al hook del avatar por defecto (esto funciona tanto con un simple ID de usuario o email como con el propio objeto de usuario).
// Aplicar filtro
add_filter( 'get_avatar' , 'my_custom_avatar' , 1 , 5 );
function my_custom_avatar( $avatar, $id_or_email, $size, $default, $alt ) {
$user = false;
if ( is_numeric( $id_or_email ) ) {
$id = (int) $id_or_email;
$user = get_user_by( 'id' , $id );
} elseif ( is_object( $id_or_email ) ) {
if ( ! empty( $id_or_email->user_id ) ) {
$id = (int) $id_or_email->user_id;
$user = get_user_by( 'id' , $id );
}
} else {
$user = get_user_by( 'email', $id_or_email );
}
if ( $user && is_object( $user ) ) {
if ( $user->data->ID == '1' ) {
$avatar = 'TU_URL_DE_IMAGEN_NUEVA';
$avatar = "<img alt='{$alt}' src='{$avatar}' class='avatar avatar-{$size} photo' height='{$size}' width='{$size}' />";
}
}
return $avatar;
}

¿Se supone que $default
es el avatar predeterminado en caso de que fallen estas declaraciones if?

Como se indica en el codex, $default es la URL del avatar predeterminado cuando no se ha seleccionado ningún avatar. El predeterminado de WordPress utiliza "Mystery man"

https://codex.wordpress.org/Function_Reference/get_avatar para más información

Añade tu archivo avatar.jpg a la carpeta de imágenes de tu tema hijo y el siguiente código al archivo functions.php de tu tema hijo:
add_filter( 'get_avatar' , 'add_custom_avatar' , 1 , 5 );
function add_custom_avatar( $avatar, $id_or_email, $size, $default, $alt ) {
$user = false;
if ( is_numeric( $id_or_email ) ) {
$id = (int) $id_or_email;
$user = get_user_by( 'id' , $id );
} elseif ( is_object( $id_or_email ) ) {
if ( ! empty( $id_or_email->user_id ) ) {
$id = (int) $id_or_email->user_id;
$user = get_user_by( 'id' , $id );
}
} else {
$user = get_user_by( 'email', $id_or_email );
}
if ( $user && is_object( $user ) ) {
if ( $user->data->ID == '1' ) {
$avatar = sprintf( '%s/images/avatar.jpg', get_stylesheet_directory_uri() );
$avatar = "<img alt='{$alt}' src='{$avatar}' class='avatar avatar-{$size} photo' height='{$size}' width='{$size}' />";
}
}
return $avatar;
}
